package com.app.twth.service;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import androidx.annotation.Nullable;

import com.app.twth.app.Constant;
import com.app.twth.app.MyApplication;
import com.app.twth.satoprinter.Printer;
import com.app.twth.ui.printer.DeviceConnFactoryManager;
import com.app.twth.ui.printer.PrintTypeBean;
import com.app.twth.utils.Base64Utils;
import com.app.twth.utils.PDF2Bitmap;
import com.app.twth.utils.PreferencesUtil;
import com.app.twth.utils.ToastUtil;
import com.app.twth.utils.Utils;
import com.smart.command.CpclCommand;
import com.smart.command.EscCommand;

import org.greenrobot.eventbus.EventBus;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

/**
 * Created by admin on 2024/6/19.
 * Description:
 * Encoding: utf-8
 */
public class PrinterService extends Service {
    private String TAG = getClass().getSimpleName();
    int count;
    long timeMillis;
    public String connectName;
    String printerType;
    boolean timeout = false;
    public String printHint = "";
    public boolean mIsConnected = false;
    PrintTypeBean printTypeBean = new PrintTypeBean();
    Printer mPrinter;
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Printer.MESSAGE_STATE_CHANGE:
                    switch (msg.arg1) {
                        case Printer.STATE_CONNECTED:
                            count = 0;
                            printHint = "";
                            printTypeBean.setType(Constant.printSuccess);
                            printTypeBean.setValue(connectName);
                            printTypeBean.setValue1("STATE_CONNECTED");
                            EventBus.getDefault().post(printTypeBean);
                            mIsConnected = true;
                            Log.e(TAG, "printerType:" + printerType);
                            if (Utils.isEmpty(printerType)) {
                                return;
                            }
                            if (printerType.equals("WIFI")) {
                                startTime();
                            }

                            break;
                        case Printer.STATE_CONNECTING:
                            printHint = "state connecting";
                            Log.e(TAG, "STATE_CONNECTING");
                            printTypeBean.setType(Constant.printConnecting);
                            printTypeBean.setValue(connectName);
                            printTypeBean.setValue1("STATE_CONNECTING");
                            EventBus.getDefault().post(printTypeBean);
                            mIsConnected = false;
                            break;
                        case Printer.STATE_NONE:
                            Log.e(TAG, "STATE_NONE");
                            printHint = "state none";
                            printTypeBean.setType(Constant.printFailure);
                            printTypeBean.setValue(connectName);
                            printTypeBean.setValue1("STATE_NONE");
                            EventBus.getDefault().post(printTypeBean);
                            mIsConnected = false;
                            endTime();
                            if (System.currentTimeMillis() - timeMillis < 1500) {//1.5秒内触发一次
                                return;
                            }
                            timeMillis = System.currentTimeMillis();
                            count++;
                            if (count > 3) {
                                return;
                            }
                            firstConnect();
                            break;
                    }
                    break;
                case Printer.MESSAGE_READ:
                    num = 0;
                    switch (msg.arg1) {
                        case Printer.PROCESS_GET_STATUS:
                            byte[] report = (byte[]) msg.obj;
                            printHint = "";
                            if ((report[0] & Printer.STATUS_1ST_BYTE_PAPER_EMPTY) == Printer.STATUS_1ST_BYTE_PAPER_EMPTY) {
                                printHint = printHint + "Paper Empty.";
                            }
                            if ((report[0] & Printer.STATUS_1ST_BYTE_COVER_OPEN) == Printer.STATUS_1ST_BYTE_COVER_OPEN) {
                                printHint = printHint + "Cover open.";
                            }
                            if ((report[0] & Printer.STATUS_1ST_BYTE_CUTTER_JAMMED) == Printer.STATUS_1ST_BYTE_CUTTER_JAMMED) {
                                printHint = printHint + "Cutter jammed.";
                            }
                            if ((report[0] & Printer.STATUS_1ST_BYTE_TPH_OVERHEAT) == Printer.STATUS_1ST_BYTE_TPH_OVERHEAT) {
                                printHint = printHint + "TPH(thermal head) overheat.";
                            }
                            if ((report[0] & Printer.STATUS_1ST_BYTE_AUTO_SENSING_FAILURE) == Printer.STATUS_1ST_BYTE_AUTO_SENSING_FAILURE) {
                                printHint = printHint + "Gap detection error. (Auto-sensing failure).";
                            }
                            if ((report[0] & Printer.STATUS_1ST_BYTE_RIBBON_END_ERROR) == Printer.STATUS_1ST_BYTE_RIBBON_END_ERROR) {
                                printHint = printHint + "Ribbon end error.";
                            }
                            if (report.length == 2) {
                                if ((report[1] & Printer.STATUS_2ND_BYTE_BUILDING_IN_IMAGE_BUFFER) == Printer.STATUS_2ND_BYTE_BUILDING_IN_IMAGE_BUFFER) {
                                    printHint = printHint + "On building label to be printed in image buffer.";
                                }
                                if ((report[1] & Printer.STATUS_2ND_BYTE_PRINTING_IN_IMAGE_BUFFER) == Printer.STATUS_2ND_BYTE_PRINTING_IN_IMAGE_BUFFER) {
                                    printHint = printHint + "On printing label in image buffer.";
                                }
                                if ((report[1] & Printer.STATUS_2ND_BYTE_PAUSED_IN_PEELER_UNIT) == Printer.STATUS_2ND_BYTE_PAUSED_IN_PEELER_UNIT) {
                                    printHint = printHint + "Issued label is paused in peeler unit.";
                                }
                            }
                            if (!Utils.isEmpty(printHint)) {
                                printHint = "Printer : " + printHint;
                                Log.e(TAG, "printHint:" + printHint);
                            }
                            break;
                        case Printer.PROCESS_GET_INFORMATION_MODEL_NAME:
                        case Printer.PROCESS_GET_INFORMATION_FIRMWARE_VERSION:
                        case Printer.PROCESS_EXECUTE_DIRECT_IO:
                            Log.e(TAG, "2MESSAGE_READ:" + (String) msg.obj);
                            break;
                    }
                    break;
                case Printer.MESSAGE_DEVICE_NAME:
                    String mConnectedDeviceName = msg.getData().getString(Printer.DEVICE_NAME);
                    Log.e(TAG, "MESSAGE_DEVICE_NAME:" + mConnectedDeviceName);
                    break;
                case Printer.MESSAGE_TOAST:
                    printHint = msg.getData().getString(Printer.TOAST);
                    Log.e(TAG, "MESSAGE_TOAST:" + msg.getData().getString(Printer.TOAST));
                    break;
                case Printer.MESSAGE_LOG:
                    Log.e(TAG, "MESSAGE_LOG:" + msg.getData().getString(Printer.LOG));
                    break;
                case Printer.MESSAGE_BLUETOOTH_DEVICE_SET:
                    Log.e(TAG, "MESSAGE_BLUETOOTH_DEVICE_SET");
                    if (msg.obj == null) {
                        ToastUtil.showToast("No paired device");
                    }
                    break;
                case Printer.MESSAGE_USB_DEVICE_SET:
                    Log.e(TAG, "MESSAGE_USB_DEVICE_SET");
                    if (msg.obj == null) {
                        ToastUtil.showToast("No connected device");
                    }
                    break;
                case Printer.MESSAGE_NETWORK_DEVICE_SET:
                    Log.e(TAG, "MESSAGE_NETWORK_DEVICE_SET");
                    if (msg.obj == null) {
                        ToastUtil.showToast("No connectable device");
                    }
                    break;
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "==========onCreate===========");
        mPrinter = new Printer(this, mHandler, Looper.myLooper());
    }

    // 服务启动
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "==========onStartCommand===========");
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //服务绑定成功后返回一个中间人对象
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    public class MyBinder extends Binder {
        public PrinterService getService() {
            return PrinterService.this;
        }
    }

    public void firstConnect() {
        printerType = PreferencesUtil.getString(PrinterService.this, "printerType");
        if (Utils.isEmpty(printerType)) {
            return;
        }

        String printerValue = PreferencesUtil.getString(PrinterService.this, "printerValue");
        Log.e(TAG, "printerValue:" + printerValue);

        if (printerType.equals("WIFI")) {
            try {
                connectWifi(printerValue, PreferencesUtil.getInt(PrinterService.this, "printerPort", 9100));
                return;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void connectWifi(String ip, int port) {
        printHint = "";
        if (mPrinter.isConnected()) {
            mPrinter.disconnect();
        }
        try {
            if (Utils.isEmpty(printerType)) {
                printerType = "WIFI";
            }
            endTime();
            PreferencesUtil.putString(PrinterService.this, "printerType", "WIFI");
            PreferencesUtil.putString(PrinterService.this, "printerValue", ip);
            PreferencesUtil.putInt(PrinterService.this, "printerPort", port);
            connectName = ip;
            timeout = false;
            Log.e(TAG, "ip:" + ip + ",port:" + port);
            mPrinter.connect(ip, port, 10000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isConnected() {
        return mPrinter.isConnected();
    }

    public void disconnect() {
        try {
            count = 3;//自动断开不做重来
            mPrinter.disconnect();
            mIsConnected = false;
            printTypeBean.setType(Constant.printFailure);
            printTypeBean.setValue("Printer Name");
            printTypeBean.setValue1("please connect your printer!");
            EventBus.getDefault().post(printTypeBean);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 打印PDF
     *
     * @param path
     */
    public void printPDF(String path) {
        long startTime = System.currentTimeMillis();
        Log.e(TAG, "mPrinter.drawBitmap:" + startTime);
        PDF2Bitmap p = new PDF2Bitmap(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            p.openPDF(path, 780, 1200);// PDF打印的最大宽度maxWeight
        }
        ArrayList<Bitmap> mps = p.getMbitmaps();
        if (mps.size() == 0) {
            Log.e(TAG, "kong:");
            return;
        }
        Log.e(TAG, "mps.size():" + mps.size());
        for (int i = 0; i < mps.size(); i++) {
            Bitmap bitmap = mps.get(i);
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            //832 , 1216
            int horizontalStartPosition = 20;
            int verticalStartPosition = 15;
            if (832 - width > 0) {
                horizontalStartPosition = (832 - width) / 2;
            }
            if (1200 - height > 0) {
                verticalStartPosition = (1200 - height) / 2;
            }
            Log.e(TAG, "" + horizontalStartPosition);
            Log.e(TAG, "verticalStartPosition:" + verticalStartPosition);
            try {
                if (mIsConnected) {
                    mPrinter.drawCompressionImage(bitmap, horizontalStartPosition, verticalStartPosition, width, 50, true);
                    mPrinter.print(1, 1);
                } else {
                    //Init command
                    EscCommand esc = new EscCommand();
                    //printerWidth为打印机热敏片可打印宽度。80mm打印机可打印范围为576点（或像素）。58mm打印机可打印范围为384点（或像素）
                    esc.addOriginRasterBitImage(bitmap, 600, 576);
                    esc.addPrintAndFeedLines((byte) 3);
                    // Send cpcl data
                    DeviceConnFactoryManager.getDeviceConnFactoryManager().sendDataImmediately(esc.getCommand());

//                CpclCommand cpcl = new CpclCommand();
//                cpcl.addEGraphics(20, 20, 600, 127, bitmap);
//                //Print
//                cpcl.addPrint();
//                Vector<Byte> datas = cpcl.getCommand();
//
//                // Send cpcl data
//                DeviceConnFactoryManager.getDeviceConnFactoryManager().sendDataImmediately(datas);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static final String CRASH_REPORTER_EXTENSION = ".pdf";

    public void printPDFBase64(String pdf_b64) {
        new Thread(new Runnable() {
            @Override

            public void run() {
                byte[] decode = Base64Utils.decode(pdf_b64.toCharArray());
                String path = MyApplication.PATH_IMG + File.separator + "temp-" + System.currentTimeMillis() + CRASH_REPORTER_EXTENSION;
                Log.e(TAG, "path:" + path);
                OutputStream out = null;
                try {
                    out = new FileOutputStream(path);
                    InputStream is = new ByteArrayInputStream(decode);
                    byte[] buff = new byte[1024];
                    int len = 0;
                    while ((len = is.read(buff)) != -1) {
                        out.write(buff, 0, len);
                    }
                    is.close();
                    out.close();

                    PDF2Bitmap p = new PDF2Bitmap(PrinterService.this);

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        p.openPDF(path, 780, 1200);// PDF打印的最大宽度maxWeight
                    }

                    ArrayList<Bitmap> mps = p.getMbitmaps();
                    if (mps == null || mps.size() == 0) {
                        System.out.println("kong");
                        return;
                    }
                    Log.e(TAG, "mps.size():" + mps.size());
                    for (int i = 0; i < mps.size(); i++) {
                        Bitmap bitmap = mps.get(i);
                        int width = bitmap.getWidth();
                        int height = bitmap.getHeight();

                        int horizontalStartPosition = 20;
                        int verticalStartPosition = 15;
                        if (832 - width > 0) {
                            horizontalStartPosition = (832 - width) / 2;
                        }
                        if (1200 - height > 0) {
                            verticalStartPosition = (1200 - height) / 2;
                        }
                        Log.e(TAG, "" + horizontalStartPosition);
                        Log.e(TAG, "verticalStartPosition:" + verticalStartPosition);
                        try {
                            if (mIsConnected) {
                                mPrinter.drawCompressionImage(bitmap, horizontalStartPosition, verticalStartPosition, width, 50, true);
                                mPrinter.print(1, 1);
                            } else {
                                CpclCommand cpcl = new CpclCommand();
                                //                            //Set sheet height and print copies
//                            cpcl.addInitializePrinter(1130, 1);
//                            //Set alignment to center
//                            cpcl.addJustification(CpclCommand.ALIGNMENT.CENTER);

                                cpcl.addEGraphics(30, 30, 385, 127, bitmap);
                                //Print
                                cpcl.addPrint();
                                Vector<Byte> datas = cpcl.getCommand();

                                // Send cpcl data
                                DeviceConnFactoryManager.getDeviceConnFactoryManager().sendDataImmediately(datas);
                            }
                            Log.e(TAG, "mPrinter.drawBitmap");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }


    int num = 1;
    int sum = 20;
    Timer timer;

    public void startTime() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                num++;
                Log.e(TAG, "sum:" + sum + ",num:" + num);
                if (num > sum) {
                    num = 1;
                    mPrinter.disconnect();
                } else {
                    mPrinter.getStatus(false);
                }
            }
        }, 2 * 1000, 2 * 1000);
    }

    private void endTime() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        try {
            if (mPrinter != null) {
                if (mPrinter.isConnected()) {
                    mPrinter.disconnect();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        endTime();
    }

}
